package com.sgchen.demo.controller;


import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson2.JSONObject;
import com.sgchen.demo.config.AjaxResult;
import com.sgchen.demo.entity.po.AccountPo;
import com.sgchen.demo.entity.po.ChildAccountPo;
import com.sgchen.demo.service.AccountService;
import com.sgchen.security.annotation.DesensitizedUnit;
import com.sgchen.security.annotation.EncryptRequest;
import com.sgchen.security.annotation.ReqDecryptField;
import com.sgchen.security.config.SecretConfig;
import com.sgchen.security.enums.DesensitizedMode;
import com.sgchen.security.handler.CryptoTableHandler;
import com.sgchen.security.util.CryptoAsymmetricUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import javax.annotation.Resource;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author sgchen
 * @date 2024/2/6 11:37
 */
@RestController
@RequestMapping("account")
public class AccountController {

    private String uploadDir = "D:\\data";

    @Resource
    private AccountService accountService;

    @Autowired
    private CryptoTableHandler cryptoTableHandler;


    /**
     * 添加一个账号
     *
     * @param accountPo
     */
    @PostMapping("/addByWrapper")
    @EncryptRequest
    public AjaxResult addAccount(@RequestBody AccountPo accountPo) {
        accountService.addAccount(accountPo);
        return AjaxResult.success();
    }

    /**
     * 查询所有账号
     *
     * @return
     */
    @PostMapping("/queryAllWrapper")
    @EncryptRequest
    public AjaxResult queryAllWrapper() {
        List<AccountPo> accountPos = accountService.queryAllWrapper();
        return AjaxResult.success(accountPos);
    }


    /**
     * 通过账号名更新密码
     *
     * @param account
     * @param password
     */
    @PostMapping("/updatePasswordByAccount")
    @EncryptRequest
    public AjaxResult updatePasswordByAccount(String account, String password) {
        accountService.updatePasswordByAccount(account, password);
        return AjaxResult.success();
    }

    @PostMapping("/updateByIdWrapper")
    @EncryptRequest
    public AjaxResult updateByIdWrapper(@RequestBody ChildAccountPo accountPo) {
        accountService.updateByIdWrapper(accountPo);
        return AjaxResult.success();
    }

    @PostMapping("/updateByIdUpdateWrapper")
    @EncryptRequest
    public AjaxResult updateByIdUpdateWrapper(@RequestBody AccountPo accountPo) {
        accountService.updateByIdUpdateWrapper(accountPo);
        return AjaxResult.success();
    }

    @PostMapping("/updateUpdateWrapper")
    @EncryptRequest
    public AjaxResult updateUpdateWrapper(@RequestBody AccountPo accountPo) {
        accountService.updateUpdateWrapper(accountPo);
        return AjaxResult.success();
    }


    @PostMapping("/getInfoByMapperParams")
    @EncryptRequest
    public AjaxResult getInfoByMapperParams(@RequestBody AccountPo accountPo) {
        List<AccountPo> result = accountService.getInfoByMapperParams(accountPo);
        return AjaxResult.success(result);
    }

    @PostMapping("/getInfoByWrapper")
    @EncryptRequest
    public AjaxResult getInfoByWrapper(@RequestBody AccountPo accountPo) {
        List<AccountPo> result = accountService.getInfoByWrapper(accountPo);
//        List<AccountPo> result = new ArrayList<>();
//        AccountPo accountPo1 = new AccountPo();
//        accountPo1.setAccount("124511");
//        result.add(accountPo1);
        return AjaxResult.success(result);
    }

    @PostMapping("/getInfo")
    @EncryptRequest(
            decryptField = {
                    @ReqDecryptField(field = "account"),
                    @ReqDecryptField(field = "userName"),
                    @ReqDecryptField(field = "test")
            }
    )
    public AjaxResult getInfo(@RequestBody AccountPo accountPo) {
        System.out.println(JSONObject.toJSONString(accountPo));
        return AjaxResult.success(accountPo);
    }

    @PostMapping("/listByMapperEntity")
    @EncryptRequest({
            @DesensitizedUnit(field = "account", mode = DesensitizedMode.mobile)
    })
    public AjaxResult listByMapperEntity(@RequestBody AccountPo accountPo) {
        List<ChildAccountPo> result = accountService.listByMapperEntity(accountPo);
        return AjaxResult.success(result);
    }

    @PostMapping("/infoByWrapperId")
    @EncryptRequest
    public AjaxResult infoByWrapperId(@RequestBody AccountPo accountPo) {
        AccountPo result = accountService.infoByWrapperId(accountPo.getId());
        return AjaxResult.success(result);
    }

    @PostMapping("/publicEncrypt")
    public AjaxResult publicEncrypt(@RequestParam String publicKey,@RequestParam String clientKey) {
        SecretConfig secretConfig = SpringUtil.getBean(SecretConfig.class);
        PublicKey publicKeyObj = CryptoAsymmetricUtil.restorePublicKey(publicKey,secretConfig.getRequestAsymmetricMode());
        String encrypted = CryptoAsymmetricUtil.encryptWithPublicKey(clientKey, publicKeyObj,secretConfig.getRequestAsymmetricMode());
        return AjaxResult.success(encrypted);
    }

    /**
     * 单文件上传接口
     */
    @PostMapping("/upload")
    public ResponseEntity<Map<String, Object>> uploadFile(@RequestParam("file") MultipartFile file,
                                                          @RequestParam("desc") String desc) {
        Map<String, Object> response = new HashMap<>();

        try {
            // 确保上传目录存在
            Path uploadPath = Paths.get(uploadDir);
            if (!Files.exists(uploadPath)) {
                Files.createDirectories(uploadPath);
            }

            // 获取文件名并处理
            String fileName = StringUtils.cleanPath(file.getOriginalFilename());
            if (fileName.contains("..")) {
                response.put("success", false);
                response.put("message", "文件名包含非法字符");
                return ResponseEntity.badRequest().body(response);
            }

            // 生成唯一文件名（可选）
            String uniqueFileName = System.currentTimeMillis() + "_" + fileName;
            Path filePath = uploadPath.resolve(uniqueFileName);

            // 保存文件到本地
            Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);

            // 构建访问URL
            String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
                    .path("/api/files/download/")
                    .path(uniqueFileName)
                    .toUriString();

            response.put("success", true);
            response.put("fileName", uniqueFileName);
            response.put("originalFileName", fileName);
            response.put("fileSize", file.getSize());
            response.put("downloadUrl", fileDownloadUri);
            response.put("message", "文件上传成功");

            return ResponseEntity.ok(response);

        } catch (IOException e) {
            response.put("success", false);
            response.put("message", "文件上传失败: " + e.getMessage());
            return ResponseEntity.status(500).body(response);
        }
    }

    /**
     * 多文件上传接口
     */
    @PostMapping("/upload/multiple")
    public ResponseEntity<Map<String, Object>> uploadMultipleFiles(@RequestParam("files") MultipartFile[] files) {
        Map<String, Object> response = new HashMap<>();

        try {
            // 确保上传目录存在
            Path uploadPath = Paths.get(uploadDir);
            if (!Files.exists(uploadPath)) {
                Files.createDirectories(uploadPath);
            }

            Map<String, Object> uploadedFiles = new HashMap<>();

            for (MultipartFile file : files) {
                // 获取文件名并处理
                String fileName = StringUtils.cleanPath(file.getOriginalFilename());
                if (fileName.contains("..")) {
                    continue; // 跳过非法文件
                }

                // 生成唯一文件名
                String uniqueFileName = System.currentTimeMillis() + "_" + fileName;
                Path filePath = uploadPath.resolve(uniqueFileName);

                // 保存文件
                Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);

                // 构建访问URL
                String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
                        .path("/api/files/download/")
                        .path(uniqueFileName)
                        .toUriString();

                Map<String, Object> fileInfo = new HashMap<>();
                fileInfo.put("fileName", uniqueFileName);
                fileInfo.put("originalFileName", fileName);
                fileInfo.put("fileSize", file.getSize());
                fileInfo.put("downloadUrl", fileDownloadUri);

                uploadedFiles.put(fileName, fileInfo);
            }

            response.put("success", true);
            response.put("files", uploadedFiles);
            response.put("message", "多文件上传成功");

            return ResponseEntity.ok(response);

        } catch (IOException e) {
            response.put("success", false);
            response.put("message", "多文件上传失败: " + e.getMessage());
            return ResponseEntity.status(500).body(response);
        }
    }
}